﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Tecnosop.Dominio;
using Tecnosop.WebUI.Models;
using System.Web.UI;
using Tecnosop.WebUI.Infrastructure.Notification;

namespace Tecnosop.WebUI.Controllers
{
    [Authorize]
    public partial class MedicionController : Controller
    {
        private Entidades db = new Entidades();

        #region CRUD

        public virtual ViewResult Index()
        {
            var mediciones = db.MEDICIONES.Include(m => m.EQUIPO_EN_CONVENIO);
            return View(mediciones.ToList());
        }

        public virtual ActionResult Details(int id)
        {
            return View(db.MEDICIONES.Find(id));
        }

        [ActionName("Create")]
        public virtual ActionResult BusquedaEquipoEnConvenioPaso1()
        {
            return View();
        }

        [HttpPost, ActionName("Create")]
        public virtual ActionResult BusquedaEquipoEnConvenioPaso1(BusquedaEquipoEnConvenio busqueda)
        {
            int id_equipo_en_convenio = 0;

            try
            {
                if (busqueda.CONSIGNACION == null && String.IsNullOrEmpty(busqueda.NUMERO_DE_SERIE))
                {
                    ModelState.AddModelError("CONSIGNACION", " ");
                    ModelState.AddModelError("NUMERO_DE_SERIE", " ");
                    ModelState.AddModelError("", "Debe ingresar al menos uno de los datos del equipo");
                }
                else if (busqueda.CONSIGNACION != null && !String.IsNullOrEmpty(busqueda.NUMERO_DE_SERIE))
                {
                    if (!db.EQUIPO_EN_CONVENIO.Single(e => e.NUMERO_SERIE == busqueda.NUMERO_DE_SERIE)
                        .Equals(db.EQUIPO_EN_CONVENIO.Single(e => e.CONSIGNACION_EQUIPO.CONSIGNACION == busqueda.CONSIGNACION)))
                    {
                        ModelState.AddModelError("CONSIGNACION", " ");
                        ModelState.AddModelError("NUMERO_DE_SERIE", " ");
                        ModelState.AddModelError("", "La consignación y el número de serie no corresponden al mismo equipo.");
                    }
                }

                if (!String.IsNullOrEmpty(busqueda.NUMERO_DE_SERIE))
                {
                    id_equipo_en_convenio = db.EQUIPO_EN_CONVENIO.Single(e => e.NUMERO_SERIE == busqueda.NUMERO_DE_SERIE).NUMERO_EQUIPO_EN_CONVENIO;
                    if (db.EQUIPO_EN_CONVENIO.Find(busqueda.NUMERO_CONVENIO, id_equipo_en_convenio) == null)
                    {
                        ModelState.AddModelError("NUMERO_DE_SERIE", "El número de serie ingresado está consignado, pero no está asociado al convenio ingresado");
                    }
                }
                if (busqueda.CONSIGNACION != null)
                {
                    id_equipo_en_convenio = db.EQUIPO_EN_CONVENIO.Single(e => e.CONSIGNACION_EQUIPO.CONSIGNACION == busqueda.CONSIGNACION).NUMERO_EQUIPO_EN_CONVENIO;
                    if (db.EQUIPO_EN_CONVENIO.Find(busqueda.NUMERO_CONVENIO, id_equipo_en_convenio) == null)
                    {
                        ModelState.AddModelError("CONSIGNACION", "El número de consignación no está asociado al convenio ingresado");
                    }
                }
            }
            catch
            {
                ModelState.AddModelError("", "La consignación ingresada no existe ó\nel número de serie no está consignado");
            }

            if (ModelState.IsValid)
            {
                return RedirectToAction(MVC.Convenio.DetailsEquipoEnConvenio(busqueda.NUMERO_CONVENIO, id_equipo_en_convenio));
            }
            else
            {
                return View();
            }
        }

        //public virtual ActionResult Edit(int id)
        //{
        //    MEDICIONES mediciones = db.MEDICIONES.Find(id);
        //    ViewBag.NUMERO_CONVENIO = new SelectList(db.EQUIPO_EN_CONVENIO, "NUMERO_CONVENIO", "NUMERO_SERIE", mediciones.NUMERO_CONVENIO);
        //    return View(mediciones);
        //}

        //[HttpPost]
        //public virtual ActionResult Edit(MEDICIONES mediciones)
        //{
        //    if (ModelState.IsValid)
        //    {
        //        db.Entry(mediciones).State = EntityState.Modified;
        //        db.SaveChanges();
        //        return RedirectToAction("Index");
        //    }
        //    ViewBag.NUMERO_CONVENIO = new SelectList(db.EQUIPO_EN_CONVENIO, "NUMERO_CONVENIO", "NUMERO_SERIE", mediciones.NUMERO_CONVENIO);
        //    return View(mediciones);
        //}

        public virtual ActionResult Delete(int id)
        {
            MEDICIONES mediciones = db.MEDICIONES.Find(id);
            return View(mediciones);
        }

        [HttpPost, ActionName("Delete")]
        public virtual ActionResult DeleteConfirmed(int id)
        {            
            MEDICIONES mediciones = db.MEDICIONES.Find(id);
            db.MEDICIONES.Remove(mediciones);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        #endregion

        #region "Grid Mediciones"

        [ChildActionOnly]
        public virtual ActionResult _AddMedicionBN(int numero_convenio, int num_equipo_en_convenio)
        {
            return PartialView(new NuevaMedicionBNViewModel
                {
                    NUMERO_CONVENIO = numero_convenio,
                    NUMERO_EQUIPO_EN_CONVENIO = num_equipo_en_convenio
                });
        }

        [HttpPost]
        public virtual ActionResult AddMedicionBN(NuevaMedicionBNViewModel medicionBN)
        {
            MEDICIONES medicion = new MEDICIONES
                {
                    CONTADOR_ACTUAL_ = medicionBN.CONTADOR_ACTUAL_BN.Value,
                    FECHA_MEDICION_ = medicionBN.FECHA_MEDICION_BN,
                    NUMERO_CONVENIO = medicionBN.NUMERO_CONVENIO,
                    MEDICION__BN = true
                };

            if (TryUpdateModel(medicion))
            {
                var mediciones = db.MEDICIONES.Where(m => m.NUMERO_CONVENIO == medicionBN.NUMERO_CONVENIO && m.NUMERO_EQUIPO_EN_CONVENIO == medicion.NUMERO_EQUIPO_EN_CONVENIO && m.MEDICION__BN);
                int count = mediciones.Count();

                if (count == 0)
                {
                    EQUIPO_EN_CONVENIO e = db.EQUIPO_EN_CONVENIO.Find(medicionBN.NUMERO_CONVENIO, medicion.NUMERO_EQUIPO_EN_CONVENIO);
                    medicion.CONTADOR_ANTERIOR_ = e.CONTADOR_SALIDA_BODEGA_EQUIPO_BN;
                    medicion.FECHA_MEDICION_ANTERIOR = null;
                }
                else
                {
                    var ultimo = mediciones.ToList().Last();
                    medicion.CONTADOR_ANTERIOR_ = ultimo.CONTADOR_ACTUAL_;
                    medicion.FECHA_MEDICION_ANTERIOR = ultimo.FECHA_MEDICION_;
                }
                medicion.DIFERENCIA_ = medicion.CONTADOR_ACTUAL_ - medicion.CONTADOR_ANTERIOR_;
                medicion.MEDICION_FACTURADA = false;

                db.MEDICIONES.Add(medicion);
                db.SaveChanges();

                this.ShowMessage(MessageType.Success, "Se agregó correctamente la medición del contador blanco y negro ID: [" + medicion.ID_MEDICION + "] a este equipo.");
            }
            else
            {
                this.ShowMessage(MessageType.Error, "No se pudo agregar una medición a este equipo.");
            }
            return RedirectToAction(MVC.Convenio.DetailsEquipoEnConvenio(medicionBN.NUMERO_CONVENIO, medicionBN.NUMERO_EQUIPO_EN_CONVENIO));
        }

        [ChildActionOnly]
        public virtual ActionResult _AddMedicionColor(int numero_convenio, int num_equipo_en_convenio)
        {
            return PartialView(new NuevaMedicionColorViewModel
                {
                    NUMERO_CONVENIO = numero_convenio,
                    NUMERO_EQUIPO_EN_CONVENIO = num_equipo_en_convenio
                });
        }

        [HttpPost]
        public virtual ActionResult AddMedicionColor(NuevaMedicionColorViewModel medicionColor)
        {
            MEDICIONES medicion = new MEDICIONES
            {
                NUMERO_CONVENIO = medicionColor.NUMERO_CONVENIO,
                FECHA_MEDICION_ = medicionColor.FECHA_MEDICION_COLOR,
                CONTADOR_ACTUAL_ = medicionColor.CONTADOR_ACTUAL_COLOR.Value,
                MEDICION__BN = false
            };

            if (TryUpdateModel(medicion))
            {
                var mediciones = db.MEDICIONES.Where(m => m.NUMERO_CONVENIO == medicionColor.NUMERO_CONVENIO && m.NUMERO_EQUIPO_EN_CONVENIO == medicion.NUMERO_EQUIPO_EN_CONVENIO && !m.MEDICION__BN);
                int count = mediciones.Count();

                if (count == 0)
                {
                    EQUIPO_EN_CONVENIO e = db.EQUIPO_EN_CONVENIO.Find(medicionColor.NUMERO_CONVENIO, medicion.NUMERO_EQUIPO_EN_CONVENIO);
                    medicion.CONTADOR_ANTERIOR_ = e.CONTADOR_SALIDA_BODEGA_EQUIPO_COLOR;
                    medicion.FECHA_MEDICION_ANTERIOR = null;
                }
                else
                {
                    MEDICIONES ultimo = mediciones.ToList().Last();
                    medicion.CONTADOR_ANTERIOR_ = ultimo.CONTADOR_ACTUAL_;
                    medicion.FECHA_MEDICION_ANTERIOR = ultimo.FECHA_MEDICION_;
                }
                medicion.DIFERENCIA_ = medicion.CONTADOR_ACTUAL_ - medicion.CONTADOR_ANTERIOR_;
                medicion.MEDICION_FACTURADA = false;

                db.MEDICIONES.Add(medicion);
                db.SaveChanges();

                this.ShowMessage(MessageType.Success, "Se agregó correctamente la medición del contador a color, ID: [" + medicion.ID_MEDICION + "] a este equipo.");
            }
            else
            {
                this.ShowMessage(MessageType.Error, "No se pudo agregar una medición a este equipo.");
            }
            return RedirectToAction(MVC.Convenio.DetailsEquipoEnConvenio(medicionColor.NUMERO_CONVENIO, medicionColor.NUMERO_EQUIPO_EN_CONVENIO));
        }

        [HttpPost]
        public virtual ActionResult DeleteMedicion(int ID_MEDICION, int NUMERO_CONVENIO, int NUMERO_EQUIPO_EN_CONVENIO)
        {
            MEDICIONES medicion = db.MEDICIONES.Find(ID_MEDICION);
            bool hayError = false;

            if (medicion.MEDICION_FACTURADA)
            {
                this.ShowMessage(MessageType.Error, "No se puede eliminar una medición que ya está facturada");
                hayError = true;
            }

            if (medicion.DETALLE_MEDICION.Any())
            {
                this.ShowMessage(MessageType.Error, "No se puede eliminar la medición porque está en el detalle de una factura. Elimine el detalle de la factura primero");
                hayError = true;
            }

            DateTime fechaUltimaMedicion = db.EQUIPO_EN_CONVENIO.Find(NUMERO_CONVENIO, NUMERO_EQUIPO_EN_CONVENIO)
                                                .MEDICIONES./*ToArray().*/OrderByDescending(e => e.FECHA_MEDICION_).First().FECHA_MEDICION_;
            if (fechaUltimaMedicion > medicion.FECHA_MEDICION_)
            {
                this.ShowMessage(MessageType.Error, "No se puede eliminar una medición que tenga mediciones posteriores. Intente eliminar las últimas mediciones");
                hayError = true;
            }

            if (!hayError)
            {
                db.MEDICIONES.Remove(medicion);
                db.SaveChanges();
                this.ShowMessage(MessageType.Success, "La medición fue eliminada");
            }

            return RedirectToAction(MVC.Convenio.DetailsEquipoEnConvenio(NUMERO_CONVENIO, NUMERO_EQUIPO_EN_CONVENIO));
        }


        #endregion

        #region Busqueda

        [ChildActionOnly]
        public virtual ActionResult Search()
        {
            return PartialView();
        }

        public virtual ActionResult Busqueda()
        {
            return View();
        }

        public virtual ActionResult ResultadoBusqueda(string Criterios, string AreaBusqueda)
        {
            switch (Criterios)
            {
                case "ID":
                    int id;
                    return View(new ResultadoBusquedaMedicionViewModel
                        {
                            Resultado = Int32.TryParse(AreaBusqueda, out id) ? db.MEDICIONES.Where(m => m.ID_MEDICION == id).ToList() : new List<MEDICIONES>(),
                            CriterioParaOrdenar = Criterios
                        });
                case "Convenio":
                    int numConvenio;
                    return View(new ResultadoBusquedaMedicionViewModel
                        {
                            Resultado = Int32.TryParse(AreaBusqueda, out numConvenio) ? db.MEDICIONES.Where(m => m.NUMERO_CONVENIO == numConvenio).ToList() : new List<MEDICIONES>(),
                            CriterioParaOrdenar = Criterios
                        });
                case "Consignacion":
                    int consignacion;
                    return View(new ResultadoBusquedaMedicionViewModel
                        {
                            Resultado = Int32.TryParse(AreaBusqueda, out consignacion) ? db.MEDICIONES.Where(m => m.EQUIPO_EN_CONVENIO.CONSIGNACION_EQUIPO.CONSIGNACION == consignacion).ToList() : new List<MEDICIONES>(),
                            CriterioParaOrdenar = Criterios
                        });
                case "Serie":
                    return View(new ResultadoBusquedaMedicionViewModel
                        {
                            Resultado = db.MEDICIONES.Where(m => m.EQUIPO_EN_CONVENIO.NUMERO_SERIE.Equals(AreaBusqueda)).ToList(),
                            CriterioParaOrdenar = Criterios
                        });
                default:
                    return PartialView(Views.Search);
            }
        }

        #endregion

        #region Validaciones

        [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public virtual JsonResult ValidaNumeroConvenio(int NUMERO_CONVENIO)
        {
            return Json(db.CONVENIO.Any(c => c.NUMERO_CONVENIO == NUMERO_CONVENIO), JsonRequestBehavior.AllowGet);
        }

        [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public virtual JsonResult ValidaConsignacion(int CONSIGNACION)
        {
            return Json(db.CONSIGNACION_EQUIPO.Any(c => c.CONSIGNACION == CONSIGNACION), JsonRequestBehavior.AllowGet);
        }

        [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public virtual JsonResult ValidaNumeroSerie(string NUMERO_DE_SERIE)
        {
            return Json(db.CONSIGNACION_EQUIPO.Any(c => c.NUMERO_SERIE == NUMERO_DE_SERIE), JsonRequestBehavior.AllowGet);
        }

        [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public virtual JsonResult ValidaBusquedaVacia(string Criterios, string AreaBusqueda)
        {
            switch (Criterios)
            {
                case "ID":
                    int id;
                    return Json(Int32.TryParse(AreaBusqueda, out id) ? db.MEDICIONES.Any(m => m.ID_MEDICION == id) : false, JsonRequestBehavior.AllowGet);
                case "Convenio":
                    int numConvenio;
                    return Json(Int32.TryParse(AreaBusqueda, out numConvenio) ? db.MEDICIONES.Any(m => m.NUMERO_CONVENIO == numConvenio) : false, JsonRequestBehavior.AllowGet);
                case "Consignacion":
                    int consignacion;
                    return Json(Int32.TryParse(AreaBusqueda, out consignacion) ? db.MEDICIONES.Any(m => m.EQUIPO_EN_CONVENIO.CONSIGNACION_EQUIPO.CONSIGNACION == consignacion) : false, JsonRequestBehavior.AllowGet);
                case "Serie":
                    return Json(db.MEDICIONES.Any(m => m.EQUIPO_EN_CONVENIO.NUMERO_SERIE.Equals(AreaBusqueda)), JsonRequestBehavior.AllowGet);
                default:
                    return Json(false, JsonRequestBehavior.AllowGet);
            }
        }

        [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public virtual JsonResult VerificarContadorAnteriorColor(int CONTADOR_ACTUAL_COLOR, int NUMERO_EQUIPO_EN_CONVENIO)
        {
            try
            {
                EQUIPO_EN_CONVENIO equipo = db.EQUIPO_EN_CONVENIO.Single(e => e.NUMERO_EQUIPO_EN_CONVENIO == NUMERO_EQUIPO_EN_CONVENIO);

                //if (equipo.MEDICIONES.Count == 0)
                //{
                //    return Json(equipo.CONTADOR_SALIDA_BODEGA_EQUIPO_COLOR < CONTADOR_ACTUAL_, JsonRequestBehavior.AllowGet);
                //}
                //else
                if (equipo.MEDICIONES.Where(m => !m.MEDICION__BN).Count() == 0)
                {
                    return Json(equipo.CONTADOR_SALIDA_BODEGA_EQUIPO_COLOR < CONTADOR_ACTUAL_COLOR, JsonRequestBehavior.AllowGet);
                }

                MEDICIONES ultima_medicion_color = equipo.MEDICIONES.Where(m => !m.MEDICION__BN).ToList().Last();
                return Json(ultima_medicion_color.CONTADOR_ACTUAL_ < CONTADOR_ACTUAL_COLOR, JsonRequestBehavior.AllowGet);
            }
            catch
            {
                return Json(false, JsonRequestBehavior.AllowGet);
            }
        }

        [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public virtual JsonResult VerificarContadorAnteriorBN(int CONTADOR_ACTUAL_BN, int NUMERO_EQUIPO_EN_CONVENIO)
        {
            try
            {
                EQUIPO_EN_CONVENIO equipo = db.EQUIPO_EN_CONVENIO.Single(e => e.NUMERO_EQUIPO_EN_CONVENIO == NUMERO_EQUIPO_EN_CONVENIO);

                if (equipo.MEDICIONES.Where(m => m.MEDICION__BN).Count() == 0)
                {
                    return Json(equipo.CONTADOR_SALIDA_BODEGA_EQUIPO_BN < CONTADOR_ACTUAL_BN, JsonRequestBehavior.AllowGet);
                }

                MEDICIONES ultima_medicion_color = equipo.MEDICIONES.Where(m => m.MEDICION__BN).ToList().Last();
                return Json(ultima_medicion_color.CONTADOR_ACTUAL_ < CONTADOR_ACTUAL_BN, JsonRequestBehavior.AllowGet);
            }
            catch
            {
                return Json(false, JsonRequestBehavior.AllowGet);
            }
        }

        [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public virtual JsonResult VerificarFechaAnteriorColor(string FECHA_MEDICION_COLOR, int NUMERO_EQUIPO_EN_CONVENIO)
        {
            try
            {
                DateTime Fecha_medicion;
                if (!DateTime.TryParse(FECHA_MEDICION_COLOR, out Fecha_medicion))
                {
                    return Json(false, JsonRequestBehavior.AllowGet);
                }

                EQUIPO_EN_CONVENIO equipo = db.EQUIPO_EN_CONVENIO.Single(e => e.NUMERO_EQUIPO_EN_CONVENIO == NUMERO_EQUIPO_EN_CONVENIO);

                if (equipo.MEDICIONES.Where(m => !m.MEDICION__BN).Count() == 0)
                {
                    //return Json(equipo.FECHA_INSTALACION < FECHA_MEDICION_, JsonRequestBehavior.AllowGet);
                    return Json(equipo.FECHA_INSTALACION < Fecha_medicion, JsonRequestBehavior.AllowGet);
                }

                MEDICIONES ultima_medicion = equipo.MEDICIONES.Where(m => !m.MEDICION__BN).ToList().Last();

                //return Json(ultima_medicion.FECHA_MEDICION_ < FECHA_MEDICION_, JsonRequestBehavior.AllowGet);
                return Json(ultima_medicion.FECHA_MEDICION_ < Fecha_medicion, JsonRequestBehavior.AllowGet);
            }
            catch
            {
                return Json(false, JsonRequestBehavior.AllowGet);
            }
        }

        [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public virtual JsonResult VerificarFechaAnteriorBN(string FECHA_MEDICION_BN, int NUMERO_EQUIPO_EN_CONVENIO)
        {
            try
            {
                DateTime Fecha_medicion;
                if (!DateTime.TryParse(FECHA_MEDICION_BN, out Fecha_medicion))
                {
                    return Json(false, JsonRequestBehavior.AllowGet);
                }

                EQUIPO_EN_CONVENIO equipo = db.EQUIPO_EN_CONVENIO.Single(e => e.NUMERO_EQUIPO_EN_CONVENIO == NUMERO_EQUIPO_EN_CONVENIO);

                if (equipo.MEDICIONES.Where(m => m.MEDICION__BN).Count() == 0)
                {
                    //return Json(equipo.FECHA_INSTALACION < FECHA_MEDICION_, JsonRequestBehavior.AllowGet);
                    return Json(equipo.FECHA_INSTALACION < Fecha_medicion, JsonRequestBehavior.AllowGet);
                }

                MEDICIONES ultima_medicion = equipo.MEDICIONES.Where(m => m.MEDICION__BN).ToList().Last();

                //return Json(ultima_medicion.FECHA_MEDICION_ < FECHA_MEDICION_, JsonRequestBehavior.AllowGet);
                return Json(ultima_medicion.FECHA_MEDICION_ < Fecha_medicion, JsonRequestBehavior.AllowGet);
            }
            catch
            {
                return Json(false, JsonRequestBehavior.AllowGet);
            }
        }

        #endregion

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}